//============================================================================
// Name        : LinuxThread.cpp
// Author      : 
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include "pthread.h"
#include "stdlib.h"
#include "math.h"
#include "ThreadedQueue.h"
#include "sys/time.h"
#include <stdio.h>
#include <string.h>
using namespace std;

bool readLine(FILE* file, char** ac)
{
	bool ret = true;
	if ( file)
	{
		if (( fgets(*ac, 100, file) ) == NULL)
			ret = false;
	}
	return ret;
}

FILE* openFile(const char* filename)
{
	FILE* f;
	f = fopen(filename, "r");
	return f;
}

void closeFile(FILE* f)
{
	fclose(f);
}

void* getWork(void *queue)
{
   queueADT adt;
   adt = (queueADT)queue;
   while(!isTermination(adt))
   {
//	   printf("Consumer thread %ld! waiting..\n", pthread_self());
	   queueElementT elem;
	   wait_and_pop(adt, &elem);
//	   printf("Consumer thread %ld wake up, popped value %s\n", pthread_self(), elem);
   }


   printf("Consumer thread %lu finished\n" , pthread_self());
   pthread_exit(NULL);
}

void* makeWork(void* queue)
{
	queueADT adt;
	adt = (queueADT)queue;
	printf("Producer Thread #%lu!\n", pthread_self());
	FILE* f;
	char* buffer = (char*)malloc(sizeof(char)*100);
	f = openFile("./file2");
	while( readLine(f, &buffer))
	{
		printf("Letto %s\n", buffer);
//		printf("Producer Thread %ld, read value = %s", pthread_self(), buffer);
		push(adt, buffer);
//		printf("Producer Thread %ld, pushed value = %s\n", pthread_self(), buffer);
	}
	printf("PUSH TERMINATION\n");
	fclose(f);
	push(adt, "#");
	printf("Producer thread th %lu finished\n", pthread_self());
	pthread_exit(NULL);
}

int main() {
	cout << "!!!Producer Consumer!!!" << endl; // prints !!!Hello World!!!
	queueADT queue = QueueCreate();
	pthread_t pth[5];


	struct timeval tv_start,tv_stop;

	gettimeofday(&tv_start,NULL);

	pthread_create(&pth[0], NULL, getWork, (void *)queue);
	pthread_create(&pth[1], NULL, makeWork, (void *)queue);
	pthread_create(&pth[2], NULL, getWork, (void*)queue);
	pthread_create(&pth[3], NULL, getWork, (void*)queue);
	//
	pthread_join(pth[0], NULL);
	pthread_join(pth[1], NULL);
	pthread_join(pth[2], NULL);
	pthread_join(pth[3], NULL);

	gettimeofday(&tv_stop ,NULL);

	printf ("%ld,%06ld seconds\n",tv_stop.tv_sec-tv_start.tv_sec, tv_stop.tv_usec-tv_start.tv_usec);
	printf("FINISHED");
	QueueDestroy(queue);

	return 0;
}
